.486p
.model flat
.code

include equates.h
include file.h
include data.h
include kb.h
include vga.h
include 6502.h
include empty.h
include mouse.h
include sb.h
include timer.h
include config.h
include debug.h
include io.h
include gui.h
include vbe.h

public getswitch
public error2
public _error
public _exit
;----------------------------------------------------------------------------
main:;          program entry point
;----------------------------------------------------------------------------
        mov [env_ptr],ebp
        mov [data_sel],ds
        mov [argc],esi
        mov [argv],edi

        mov al,'?'                      ;check -?
        call getswitch
        mov al,1
        jnc _error
        mov al,'h'                      ;check -h
        call getswitch
        mov al,1
        jnc _error

        mov eax,0006h
        mov bx,ds
        int 31h
        jc error2
        mov [code_addr],edx
        mov word ptr [code_addr+2],cx   ;save base address

;        mov eax,8
;        mov bx,ds
;        mov cx,0ffffh
;        mov dx,cx
;        int 31h
;        jc error2                       ;set 4G limit

        mov eax,0006h
        mov bx,es
        int 31h
        shl ecx,16
        mov cx,dx
        sub ecx,[code_addr]
        mov [psp_ptr],ecx               ;save PSP ptr

        mov es,[data_sel]               ;ES=DS

        mov dword ptr [heap],8          ;heap init
        mov byte ptr [heap+4],1
        mov dword ptr [heap+8],HEAPSIZE-8*2
        mov byte ptr [heap+12],0
        mov dword ptr [heap+HEAPSIZE-8],8
        mov byte ptr [heap+HEAPSIZE-4],3

        mov ah,47h                      ;get initial path
        mov dl,0
        mov [startdir],'\'
        mov esi,offset startdir+1
        int 21h
        jnc main7
        mov [startdir],0
main7:
        mov eax,000a0000h               ;setup VGA pointers
        sub eax,[code_addr]
        mov [gfx_ptr],eax
        mov eax,000b8000h
        sub eax,[code_addr]
        mov [text_ptr],eax

        mov edx,offset ram
        add edx,0000000ffh
        and edx,0ffffff00h              ;256 byte align (for 6502 stack pointer)
        mov [ram_ptr],edx

        mov ax,0ah                      ;make nes ram descriptor
        mov bx,cs
        int 31h
        jc error2
        mov [ram_sel],eax
        mov ebx,eax
        mov eax,8
        xor ecx,ecx
        mov edx,0ffffh
        int 31h                         ;set limit to 64k
        jc error2
        mov ebx,[ram_sel]
        mov eax,7
        mov ecx,[ram_ptr]
        add ecx,[code_addr]
        mov edx,ecx
        shr ecx,16
        int 31h                         ;set base address
        jc error2
        mov fs,bx                       ;load FS with selector

        xor eax,eax                     ;clear screens
        mov ecx,264*240/4
        mov edi,offset vscreen
        rep stosd
        mov ecx,264*240/4
        mov edi,offset vscreen2
        rep stosd
        mov ax,0100h                    ;allocate 64k dos mem
        mov bx,1000h
        int 31h
        jc error2
        and eax,0ffffh
        shl eax,4
        sub eax,[code_addr]
        mov [dos_ptr],eax

        call LFNtest                    ;check LFN
        call vesainit                   ;init VESA
        call kb_init                    ;init keyboard
        call mouseinit                  ;init mouse
        call sb_init                    ;init sound
        call timer_init                 ;init 60Hz timer
        call loadconfig

        mov al,'v'                      ;check -v# param
        call getswitch
        jc main1
        mov byte ptr [vidmode],al
main1:
ife DEBUG
        call gfxmode
endif
        mov ecx,offset filename+1       ;put name in cmdline into [filename]
        mov edx,ecx
        call getarg
main3:  call nextarg
        jz main4
        jc main3
        mov byte ptr [ecx-1],' '                ;cat all args without -
main5:  mov al,[esi]
        mov [ecx],al
        inc esi
        inc ecx
        or al,al
        jnz main5
        jmp main3
main4:  cmp ecx,edx
        je main9

        dec ecx
        mov esi,ecx                     ;edx=front, esi=back

        sub esi,edx
main8:  cmp byte ptr [esi+edx-1],'\'    ;look for dir in filename
        je main11
        dec esi
        jnz main8
        jmp main10
main11:                                 ;move to rom dir
        push dword ptr [esi+edx]
        mov byte ptr [esi+edx],0
        call cd
        pop dword ptr [esi+edx]
main10:
        lea edi,[esi+edx]

if DEBUG
main9:
        call loadcart                   ;load cart
        jc _error
        mov [int_flags],DEBUG1          ;debugger entry flag
        mov [vgamode],1                 ;reset screen
        mov [debugmsg],offset msg41
        jmp cpu_init
else
        call loadcart                   ;load cart
        jnc cpu_init
main9:
        call pal_init                   ;(pal not set if loadcart failed)
        call startgui
        jmp main9
endif
;----------------------------------------------------------------------------
shutdown:;      shutdown everything
;----------------------------------------------------------------------------
        call vga_exit
        call xfree
        call mouseexit
        call sb_exit
        call timer_exit
        ret
;----------------------------------------------------------------------------
getswitch:;        look for -al#
;
;       out:
;               esi=?
;               al=#
;               C=1 if not found
;----------------------------------------------------------------------------
        call getarg
sw0:    call nextarg
        jz sw9
        jnc sw0
        cmp al,[esi]
        jne sw0
sw1:    mov al,[esi+1]
        sub al,'0'
        clc
        ret
sw9:    stc
        ret
;----------------------------------------------------------------------------
getarg:
;       out:
;               esi=arg
;               Z=1 if empty
;               C=1 if arg begins with '-' or '/'
;----------------------------------------------------------------------------
        mov esi,[argv]
        mov [argN],esi
nextarg:
        mov esi,[argN]
        mov esi,[esi]
        or esi,esi
        jz ga9
        add [argN],4
        cmp byte ptr [esi],'/'
        je ga0
        cmp byte ptr [esi],'-'
        clc
        jne ga9
ga0:    inc esi         ;Z=0
        stc
ga9:    ret

argN    dd ?
;----------------------------------------------------------------------------
error2:;        generic error
;----------------------------------------------------------------------------
        mov al,27h
;----------------------------------------------------------------------------
_error:;        shutdown everything, display error string, and exit to DOS.
;
;       in:
;               AL=error code
;
;----------------------------------------------------------------------------
        push eax
        call shutdown
        pop ecx

        and ecx,03fh
        mov edx,[errtbl+ecx*4]          ;get ptr to error string
        mov ah,09h
        int 21h

        jmp _realexit
;----------------------------------------------------------------------------
_exit:;         shutdown everything and exit to DOS
;----------------------------------------------------------------------------
        call closerom                   ;unload ROM
        call saveconfig                 ;save config
        call shutdown

        mov ah,3bh                      ;restore original dir
        mov edx,offset startdir
        int 21h
_realexit:
        mov eax,4c00h
        int 21h                         ;exit to DOS
;----------------------------------------------------------------------------
        end main
